package protocol

import (
	"encoding/binary"
)

const (
	PID_SIZE          = 4
	SID_SIZE          = 4
	RID_SIZE          = 4
	TOKEN_SIZE        = 4
	DS_SIZE           = 4
	DSCP_SIZE         = 1
	STATE_SIZE        = 1
	MRT_SIZE          = 2
	REQ_HEADER_LENGTH = PID_SIZE + SID_SIZE + RID_SIZE + TOKEN_SIZE + DS_SIZE + DSCP_SIZE + STATE_SIZE + MRT_SIZE
)

type RequestProtocolCodec struct{}

type Request_Header struct {
	ProviderID  uint32
	ServiceID   uint32
	RequestID   uint32
	Token       uint32
	DataSize    uint32
	Dscp        byte
	State       byte
	MaxRespTime uint16
}

// 0                                    32 bit
// +------------------------------------+ -----
// |             Provider ID            |
// +------------------------------------+
// |             Service  ID            |
// +------------------------------------+
// |             Request  ID            |  Header
// +------------------------------------+
// |           Validation Token         |
// +------------------------------------+
// |             Data Size              |
// +---------8-------16-------24--------+
// |   DSCP  |  State |Max Response Time|
// +------------------------------------+ -----
// |              Parameters            |
// |                 ...                |  Body

// buf已经不包含Type那一层的Header了；
// 返回值包括两部分，一个是包含ProviderID等的请求头部，第二个是包含请求参数的protobuf序列
func (codec *RequestProtocolCodec) Decode(buf []byte) (reqHeader Request_Header, data []byte, err error) {
	// 计算各个部分的偏移量
	pidOffset := 0
	sidOffset := pidOffset + PID_SIZE
	ridOffset := sidOffset + SID_SIZE
	tkOffset := ridOffset + RID_SIZE
	dsOffset := tkOffset + TOKEN_SIZE
	dscpOffset := dsOffset + DS_SIZE
	stateOffset := dscpOffset + DSCP_SIZE
	mrtOffset := stateOffset + STATE_SIZE
	dataOffset := mrtOffset + MRT_SIZE

	// 提取Header
	reqHeader.ProviderID = binary.BigEndian.Uint32(buf[pidOffset : pidOffset+PID_SIZE])
	reqHeader.ServiceID = binary.BigEndian.Uint32(buf[sidOffset : sidOffset+SID_SIZE])
	reqHeader.RequestID = binary.BigEndian.Uint32(buf[ridOffset : ridOffset+RID_SIZE])
	reqHeader.Token = binary.BigEndian.Uint32(buf[tkOffset : tkOffset+TOKEN_SIZE])
	reqHeader.DataSize = binary.BigEndian.Uint32(buf[dsOffset : dsOffset+DS_SIZE])
	reqHeader.Dscp = buf[dscpOffset]
	reqHeader.State = buf[stateOffset]
	reqHeader.MaxRespTime = binary.BigEndian.Uint16(buf[mrtOffset : mrtOffset+MRT_SIZE])

	// 提取Body
	data = make([]byte, reqHeader.DataSize)
	copy(data, buf[dataOffset:uint32(dataOffset)+reqHeader.DataSize])

	err = nil
	return
}

func (codec *RequestProtocolCodec) getHeader(reqHeader Request_Header) (header []byte, err error) {
	header = make([]byte, 0)

	header = binary.BigEndian.AppendUint32(header, reqHeader.ProviderID)
	header = binary.BigEndian.AppendUint32(header, reqHeader.ServiceID)
	header = binary.BigEndian.AppendUint32(header, reqHeader.RequestID)
	header = binary.BigEndian.AppendUint32(header, reqHeader.Token)
	header = binary.BigEndian.AppendUint32(header, reqHeader.DataSize)
	header = append(header, reqHeader.Dscp)
	header = append(header, reqHeader.State)
	header = binary.BigEndian.AppendUint16(header, reqHeader.MaxRespTime)

	err = nil
	return
}

func (codec *RequestProtocolCodec) AppendHeader(reqHeader Request_Header, body []byte) (res []byte, err error) {
	body_length := len(body)
	//reqHeader.DataSize = uint32(body_length)
	res = make([]byte, REQ_HEADER_LENGTH+body_length)
	header, _ := codec.getHeader(reqHeader)
	copy(res[:REQ_HEADER_LENGTH], header[:])
	copy(res[REQ_HEADER_LENGTH:], body[:])

	err = nil
	return
}

// AppendRawData 拼接token和rawData，返回token的size
func (codec *RequestProtocolCodec) AppendRawData(token []byte, rawData []byte) ([]byte, int) {
	token = append(token, rawData...)
	return token, len(token)
}
